home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / compiler / pyassem.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-11-11  |  28KB  |  932 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''A flow graph representation for Python bytecode'''
  5. import dis
  6. import types
  7. import sys
  8. from compiler import misc
  9. from compiler.consts import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS
  10.  
  11. class FlowGraph:
  12.     
  13.     def __init__(self):
  14.         self.current = self.entry = Block()
  15.         self.exit = Block('exit')
  16.         self.blocks = misc.Set()
  17.         self.blocks.add(self.entry)
  18.         self.blocks.add(self.exit)
  19.  
  20.     
  21.     def startBlock(self, block):
  22.         if self._debug:
  23.             if self.current:
  24.                 print 'end', repr(self.current)
  25.                 print '    next', self.current.next
  26.                 print '   ', self.current.get_children()
  27.             
  28.             print repr(block)
  29.         
  30.         self.current = block
  31.  
  32.     
  33.     def nextBlock(self, block = None):
  34.         if block is None:
  35.             block = self.newBlock()
  36.         
  37.         self.current.addNext(block)
  38.         self.startBlock(block)
  39.  
  40.     
  41.     def newBlock(self):
  42.         b = Block()
  43.         self.blocks.add(b)
  44.         return b
  45.  
  46.     
  47.     def startExitBlock(self):
  48.         self.startBlock(self.exit)
  49.  
  50.     _debug = 0
  51.     
  52.     def _enable_debug(self):
  53.         self._debug = 1
  54.  
  55.     
  56.     def _disable_debug(self):
  57.         self._debug = 0
  58.  
  59.     
  60.     def emit(self, *inst):
  61.         if self._debug:
  62.             print '\t', inst
  63.         
  64.         if inst[0] in ('RETURN_VALUE', 'YIELD_VALUE'):
  65.             self.current.addOutEdge(self.exit)
  66.         
  67.         if len(inst) == 2 and isinstance(inst[1], Block):
  68.             self.current.addOutEdge(inst[1])
  69.         
  70.         self.current.emit(inst)
  71.  
  72.     
  73.     def getBlocksInOrder(self):
  74.         '''Return the blocks in reverse postorder
  75.  
  76.         i.e. each node appears before all of its successors
  77.         '''
  78.         for b in self.blocks.elements():
  79.             if b is self.exit:
  80.                 continue
  81.             
  82.             if not b.next:
  83.                 b.addNext(self.exit)
  84.                 continue
  85.         
  86.         order = dfs_postorder(self.entry, { })
  87.         order.reverse()
  88.         self.fixupOrder(order, self.exit)
  89.         if self.exit not in order:
  90.             order.append(self.exit)
  91.         
  92.         return order
  93.  
  94.     
  95.     def fixupOrder(self, blocks, default_next):
  96.         '''Fixup bad order introduced by DFS.'''
  97.         self.fixupOrderHonorNext(blocks, default_next)
  98.         self.fixupOrderForward(blocks, default_next)
  99.  
  100.     
  101.     def fixupOrderHonorNext(self, blocks, default_next):
  102.         '''Fix one problem with DFS.
  103.  
  104.         The DFS uses child block, but doesn\'t know about the special
  105.         "next" block.  As a result, the DFS can order blocks so that a
  106.         block isn\'t next to the right block for implicit control
  107.         transfers.
  108.         '''
  109.         index = { }
  110.         for i in range(len(blocks)):
  111.             index[blocks[i]] = i
  112.         
  113.         for i in range(0, len(blocks) - 1):
  114.             b = blocks[i]
  115.             n = blocks[i + 1]
  116.             if not (b.next) and b.next[0] == default_next or b.next[0] == n:
  117.                 continue
  118.             
  119.             cur = b
  120.             chain = []
  121.             elt = cur
  122.             while elt.next and elt.next[0] != default_next:
  123.                 chain.append(elt.next[0])
  124.                 elt = elt.next[0]
  125.             l = []
  126.             for b in chain:
  127.                 if not index[b] > i:
  128.                     raise AssertionError
  129.                 l.append((index[b], b))
  130.             
  131.             l.sort()
  132.             l.reverse()
  133.             for j, b in l:
  134.                 del blocks[index[b]]
  135.             
  136.             blocks[i:i + 1] = [
  137.                 cur] + chain
  138.             for i in range(len(blocks)):
  139.                 index[blocks[i]] = i
  140.             
  141.         
  142.  
  143.     
  144.     def fixupOrderForward(self, blocks, default_next):
  145.         '''Make sure all JUMP_FORWARDs jump forward'''
  146.         index = { }
  147.         chains = []
  148.         cur = []
  149.         for b in blocks:
  150.             index[b] = len(chains)
  151.             cur.append(b)
  152.             if b.next and b.next[0] == default_next:
  153.                 chains.append(cur)
  154.                 cur = []
  155.                 continue
  156.         
  157.         chains.append(cur)
  158.         while None:
  159.             constraints = []
  160.             for i in range(len(chains)):
  161.                 l = chains[i]
  162.                 for b in l:
  163.                     for c in b.get_children():
  164.                         if index[c] < i:
  165.                             forward_p = 0
  166.                             for inst in b.insts:
  167.                                 if inst[0] == 'JUMP_FORWARD':
  168.                                     if inst[1] == c:
  169.                                         forward_p = 1
  170.                                     
  171.                                 inst[1] == c
  172.                             
  173.                             if not forward_p:
  174.                                 continue
  175.                             
  176.                             constraints.append((index[c], i))
  177.                             continue
  178.                     
  179.                 
  180.             
  181.             if not constraints:
  182.                 break
  183.             
  184.             (goes_before, a_chain) = constraints[0]
  185.             if not a_chain > goes_before:
  186.                 raise AssertionError
  187.             c = chains[a_chain]
  188.             chains.insert(goes_before, c)
  189.             continue
  190.             del blocks[:]
  191.             for c in chains:
  192.                 for b in c:
  193.                     blocks.append(b)
  194.                 
  195.             
  196.  
  197.     
  198.     def getBlocks(self):
  199.         return self.blocks.elements()
  200.  
  201.     
  202.     def getRoot(self):
  203.         '''Return nodes appropriate for use with dominator'''
  204.         return self.entry
  205.  
  206.     
  207.     def getContainedGraphs(self):
  208.         l = []
  209.         for b in self.getBlocks():
  210.             l.extend(b.getContainedGraphs())
  211.         
  212.         return l
  213.  
  214.  
  215.  
  216. def dfs_postorder(b, seen):
  217.     '''Depth-first search of tree rooted at b, return in postorder'''
  218.     order = []
  219.     seen[b] = b
  220.     for c in b.get_children():
  221.         if c in seen:
  222.             continue
  223.         
  224.         order = order + dfs_postorder(c, seen)
  225.     
  226.     order.append(b)
  227.     return order
  228.  
  229.  
  230. class Block:
  231.     _count = 0
  232.     
  233.     def __init__(self, label = ''):
  234.         self.insts = []
  235.         self.inEdges = misc.Set()
  236.         self.outEdges = misc.Set()
  237.         self.label = label
  238.         self.bid = Block._count
  239.         self.next = []
  240.         Block._count = Block._count + 1
  241.  
  242.     
  243.     def __repr__(self):
  244.         if self.label:
  245.             return '<block %s id=%d>' % (self.label, self.bid)
  246.         return '<block id=%d>' % self.bid
  247.  
  248.     
  249.     def __str__(self):
  250.         insts = map(str, self.insts)
  251.         return '<block %s %d:\n%s>' % (self.label, self.bid, '\n'.join(insts))
  252.  
  253.     
  254.     def emit(self, inst):
  255.         op = inst[0]
  256.         if op[:4] == 'JUMP':
  257.             self.outEdges.add(inst[1])
  258.         
  259.         self.insts.append(inst)
  260.  
  261.     
  262.     def getInstructions(self):
  263.         return self.insts
  264.  
  265.     
  266.     def addInEdge(self, block):
  267.         self.inEdges.add(block)
  268.  
  269.     
  270.     def addOutEdge(self, block):
  271.         self.outEdges.add(block)
  272.  
  273.     
  274.     def addNext(self, block):
  275.         self.next.append(block)
  276.         if not len(self.next) == 1:
  277.             raise AssertionError, map(str, self.next)
  278.  
  279.     _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'YIELD_VALUE', 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
  280.     
  281.     def pruneNext(self):
  282.         """Remove bogus edge for unconditional transfers
  283.  
  284.         Each block has a next edge that accounts for implicit control
  285.         transfers, e.g. from a JUMP_IF_FALSE to the block that will be
  286.         executed if the test is true.
  287.  
  288.         These edges must remain for the current assembler code to
  289.         work. If they are removed, the dfs_postorder gets things in
  290.         weird orders.  However, they shouldn't be there for other
  291.         purposes, e.g. conversion to SSA form.  This method will
  292.         remove the next edge when it follows an unconditional control
  293.         transfer.
  294.         """
  295.         
  296.         try:
  297.             (op, arg) = self.insts[-1]
  298.         except (IndexError, ValueError):
  299.             return None
  300.  
  301.         if op in self._uncond_transfer:
  302.             self.next = []
  303.         
  304.  
  305.     
  306.     def get_children(self):
  307.         if self.next and self.next[0] in self.outEdges:
  308.             self.outEdges.remove(self.next[0])
  309.         
  310.         return self.outEdges.elements() + self.next
  311.  
  312.     
  313.     def getContainedGraphs(self):
  314.         '''Return all graphs contained within this block.
  315.  
  316.         For example, a MAKE_FUNCTION block will contain a reference to
  317.         the graph for the function body.
  318.         '''
  319.         contained = []
  320.         for inst in self.insts:
  321.             if len(inst) == 1:
  322.                 continue
  323.             
  324.             op = inst[1]
  325.             if hasattr(op, 'graph'):
  326.                 contained.append(op.graph)
  327.                 continue
  328.         
  329.         return contained
  330.  
  331.  
  332. RAW = 'RAW'
  333. FLAT = 'FLAT'
  334. CONV = 'CONV'
  335. DONE = 'DONE'
  336.  
  337. class PyFlowGraph(FlowGraph):
  338.     super_init = FlowGraph.__init__
  339.     
  340.     def __init__(self, name, filename, args = (), optimized = 0, klass = None):
  341.         self.super_init()
  342.         self.name = name
  343.         self.filename = filename
  344.         self.docstring = None
  345.         self.args = args
  346.         self.argcount = getArgCount(args)
  347.         self.klass = klass
  348.         if optimized:
  349.             self.flags = CO_OPTIMIZED | CO_NEWLOCALS
  350.         else:
  351.             self.flags = 0
  352.         self.consts = []
  353.         self.names = []
  354.         self.freevars = []
  355.         self.cellvars = []
  356.         self.closure = []
  357.         if not list(args):
  358.             pass
  359.         self.varnames = []
  360.         for i in range(len(self.varnames)):
  361.             var = self.varnames[i]
  362.             if isinstance(var, TupleArg):
  363.                 self.varnames[i] = var.getName()
  364.                 continue
  365.         
  366.         self.stage = RAW
  367.  
  368.     
  369.     def setDocstring(self, doc):
  370.         self.docstring = doc
  371.  
  372.     
  373.     def setFlag(self, flag):
  374.         self.flags = self.flags | flag
  375.         if flag == CO_VARARGS:
  376.             self.argcount = self.argcount - 1
  377.         
  378.  
  379.     
  380.     def checkFlag(self, flag):
  381.         if self.flags & flag:
  382.             return 1
  383.  
  384.     
  385.     def setFreeVars(self, names):
  386.         self.freevars = list(names)
  387.  
  388.     
  389.     def setCellVars(self, names):
  390.         self.cellvars = names
  391.  
  392.     
  393.     def getCode(self):
  394.         '''Get a Python code object'''
  395.         if not self.stage == RAW:
  396.             raise AssertionError
  397.         self.computeStackDepth()
  398.         self.flattenGraph()
  399.         if not self.stage == FLAT:
  400.             raise AssertionError
  401.         self.convertArgs()
  402.         if not self.stage == CONV:
  403.             raise AssertionError
  404.         self.makeByteCode()
  405.         if not self.stage == DONE:
  406.             raise AssertionError
  407.         return self.newCodeObject()
  408.  
  409.     
  410.     def dump(self, io = None):
  411.         if io:
  412.             save = sys.stdout
  413.             sys.stdout = io
  414.         
  415.         pc = 0
  416.         for t in self.insts:
  417.             opname = t[0]
  418.             if opname == 'SET_LINENO':
  419.                 print 
  420.             
  421.             if len(t) == 1:
  422.                 print '\t', '%3d' % pc, opname
  423.                 pc = pc + 1
  424.                 continue
  425.             print '\t', '%3d' % pc, opname, t[1]
  426.             pc = pc + 3
  427.         
  428.         if io:
  429.             sys.stdout = save
  430.         
  431.  
  432.     
  433.     def computeStackDepth(self):
  434.         '''Compute the max stack depth.
  435.  
  436.         Approach is to compute the stack effect of each basic block.
  437.         Then find the path through the code with the largest total
  438.         effect.
  439.         '''
  440.         depth = { }
  441.         exit = None
  442.         for b in self.getBlocks():
  443.             depth[b] = findDepth(b.getInstructions())
  444.         
  445.         seen = { }
  446.         
  447.         def max_depth(b, d):
  448.             if b in seen:
  449.                 return d
  450.             seen[b] = 1
  451.             d = d + depth[b]
  452.             children = b.get_children()
  453.             if children:
  454.                 return []([ max_depth(c, d) for c in children ])
  455.             if not b.label == 'exit':
  456.                 return max_depth(self.exit, d)
  457.             return d
  458.  
  459.         self.stacksize = max_depth(self.entry, 0)
  460.  
  461.     
  462.     def flattenGraph(self):
  463.         '''Arrange the blocks in order and resolve jumps'''
  464.         if not self.stage == RAW:
  465.             raise AssertionError
  466.         pc = 0
  467.         begin = { }
  468.         end = { }
  469.         for b in self.getBlocksInOrder():
  470.             begin[b] = pc
  471.             for inst in b.getInstructions():
  472.                 insts.append(inst)
  473.                 if len(inst) == 1:
  474.                     pc = pc + 1
  475.                     continue
  476.                 self.stage == RAW
  477.                 if inst[0] != 'SET_LINENO':
  478.                     pc = pc + 3
  479.                     continue
  480.             
  481.             end[b] = pc
  482.         
  483.         pc = 0
  484.         for i in range(len(insts)):
  485.             inst = insts[i]
  486.             if len(inst) == 1:
  487.                 pc = pc + 1
  488.             elif inst[0] != 'SET_LINENO':
  489.                 pc = pc + 3
  490.             
  491.             opname = inst[0]
  492.             if self.hasjrel.has_elt(opname):
  493.                 oparg = inst[1]
  494.                 offset = begin[oparg] - pc
  495.                 insts[i] = (opname, offset)
  496.                 continue
  497.             if self.hasjabs.has_elt(opname):
  498.                 insts[i] = (opname, begin[inst[1]])
  499.                 continue
  500.         
  501.         self.stage = FLAT
  502.  
  503.     hasjrel = misc.Set()
  504.     for i in dis.hasjrel:
  505.         hasjrel.add(dis.opname[i])
  506.     
  507.     hasjabs = misc.Set()
  508.     for i in dis.hasjabs:
  509.         hasjabs.add(dis.opname[i])
  510.     
  511.     
  512.     def convertArgs(self):
  513.         '''Convert arguments from symbolic to concrete form'''
  514.         if not self.stage == FLAT:
  515.             raise AssertionError
  516.         self.consts.insert(0, self.docstring)
  517.         self.sort_cellvars()
  518.         for i in range(len(self.insts)):
  519.             t = self.insts[i]
  520.             if len(t) == 2:
  521.                 (opname, oparg) = t
  522.                 conv = self._converters.get(opname, None)
  523.                 if conv:
  524.                     self.insts[i] = (opname, conv(self, oparg))
  525.                 
  526.             conv
  527.         
  528.         self.stage = CONV
  529.  
  530.     
  531.     def sort_cellvars(self):
  532.         '''Sort cellvars in the order of varnames and prune from freevars.
  533.         '''
  534.         cells = { }
  535.         for name in self.cellvars:
  536.             cells[name] = 1
  537.         
  538.         self.cellvars = _[1]
  539.         for name in self.cellvars:
  540.             del cells[name]
  541.         
  542.         self.cellvars = self.cellvars + cells.keys()
  543.         self.closure = self.cellvars + self.freevars
  544.  
  545.     
  546.     def _lookupName(self, name, list):
  547.         """Return index of name in list, appending if necessary
  548.  
  549.         This routine uses a list instead of a dictionary, because a
  550.         dictionary can't store two different keys if the keys have the
  551.         same value but different types, e.g. 2 and 2L.  The compiler
  552.         must treat these two separately, so it does an explicit type
  553.         comparison before comparing the values.
  554.         """
  555.         t = type(name)
  556.         for i in range(len(list)):
  557.             if t == type(list[i]) and list[i] == name:
  558.                 return i
  559.         
  560.         end = len(list)
  561.         list.append(name)
  562.         return end
  563.  
  564.     _converters = { }
  565.     
  566.     def _convert_LOAD_CONST(self, arg):
  567.         if hasattr(arg, 'getCode'):
  568.             arg = arg.getCode()
  569.         
  570.         return self._lookupName(arg, self.consts)
  571.  
  572.     
  573.     def _convert_LOAD_FAST(self, arg):
  574.         self._lookupName(arg, self.names)
  575.         return self._lookupName(arg, self.varnames)
  576.  
  577.     _convert_STORE_FAST = _convert_LOAD_FAST
  578.     _convert_DELETE_FAST = _convert_LOAD_FAST
  579.     
  580.     def _convert_LOAD_NAME(self, arg):
  581.         if self.klass is None:
  582.             self._lookupName(arg, self.varnames)
  583.         
  584.         return self._lookupName(arg, self.names)
  585.  
  586.     
  587.     def _convert_NAME(self, arg):
  588.         if self.klass is None:
  589.             self._lookupName(arg, self.varnames)
  590.         
  591.         return self._lookupName(arg, self.names)
  592.  
  593.     _convert_STORE_NAME = _convert_NAME
  594.     _convert_DELETE_NAME = _convert_NAME
  595.     _convert_IMPORT_NAME = _convert_NAME
  596.     _convert_IMPORT_FROM = _convert_NAME
  597.     _convert_STORE_ATTR = _convert_NAME
  598.     _convert_LOAD_ATTR = _convert_NAME
  599.     _convert_DELETE_ATTR = _convert_NAME
  600.     _convert_LOAD_GLOBAL = _convert_NAME
  601.     _convert_STORE_GLOBAL = _convert_NAME
  602.     _convert_DELETE_GLOBAL = _convert_NAME
  603.     
  604.     def _convert_DEREF(self, arg):
  605.         self._lookupName(arg, self.names)
  606.         self._lookupName(arg, self.varnames)
  607.         return self._lookupName(arg, self.closure)
  608.  
  609.     _convert_LOAD_DEREF = _convert_DEREF
  610.     _convert_STORE_DEREF = _convert_DEREF
  611.     
  612.     def _convert_LOAD_CLOSURE(self, arg):
  613.         self._lookupName(arg, self.varnames)
  614.         return self._lookupName(arg, self.closure)
  615.  
  616.     _cmp = list(dis.cmp_op)
  617.     
  618.     def _convert_COMPARE_OP(self, arg):
  619.         return self._cmp.index(arg)
  620.  
  621.     for name, obj in locals().items():
  622.         if name[:9] == '_convert_':
  623.             opname = name[9:]
  624.             _converters[opname] = obj
  625.             continue
  626.     
  627.     del name
  628.     del obj
  629.     del opname
  630.     
  631.     def makeByteCode(self):
  632.         if not self.stage == CONV:
  633.             raise AssertionError
  634.         for t in self.insts:
  635.             opname = t[0]
  636.             if len(t) == 1:
  637.                 lnotab.addCode(self.opnum[opname])
  638.                 continue
  639.             self.lnotab = lnotab = LineAddrTable()
  640.             oparg = t[1]
  641.             if opname == 'SET_LINENO':
  642.                 lnotab.nextLine(oparg)
  643.                 continue
  644.             
  645.             (hi, lo) = twobyte(oparg)
  646.             
  647.             try:
  648.                 lnotab.addCode(self.opnum[opname], lo, hi)
  649.             continue
  650.             except ValueError:
  651.                 print opname, oparg
  652.                 print self.opnum[opname], lo, hi
  653.                 raise 
  654.                 continue
  655.             
  656.  
  657.         
  658.         self.stage = DONE
  659.  
  660.     opnum = { }
  661.     for num in range(len(dis.opname)):
  662.         opnum[dis.opname[num]] = num
  663.     
  664.     del num
  665.     
  666.     def newCodeObject(self):
  667.         if not self.stage == DONE:
  668.             raise AssertionError
  669.         if self.flags & CO_NEWLOCALS == 0:
  670.             nlocals = 0
  671.         else:
  672.             nlocals = len(self.varnames)
  673.         argcount = self.argcount
  674.         if self.flags & CO_VARKEYWORDS:
  675.             argcount = argcount - 1
  676.         
  677.         return types.CodeType(argcount, nlocals, self.stacksize, self.flags, self.lnotab.getCode(), self.getConsts(), tuple(self.names), tuple(self.varnames), self.filename, self.name, self.lnotab.firstline, self.lnotab.getTable(), tuple(self.freevars), tuple(self.cellvars))
  678.  
  679.     
  680.     def getConsts(self):
  681.         '''Return a tuple for the const slot of the code object
  682.  
  683.         Must convert references to code (MAKE_FUNCTION) to code
  684.         objects recursively.
  685.         '''
  686.         l = []
  687.         for elt in self.consts:
  688.             if isinstance(elt, PyFlowGraph):
  689.                 elt = elt.getCode()
  690.             
  691.             l.append(elt)
  692.         
  693.         return tuple(l)
  694.  
  695.  
  696.  
  697. def isJump(opname):
  698.     if opname[:4] == 'JUMP':
  699.         return 1
  700.  
  701.  
  702. class TupleArg:
  703.     '''Helper for marking func defs with nested tuples in arglist'''
  704.     
  705.     def __init__(self, count, names):
  706.         self.count = count
  707.         self.names = names
  708.  
  709.     
  710.     def __repr__(self):
  711.         return 'TupleArg(%s, %s)' % (self.count, self.names)
  712.  
  713.     
  714.     def getName(self):
  715.         return '.%d' % self.count
  716.  
  717.  
  718.  
  719. def getArgCount(args):
  720.     argcount = len(args)
  721.     if args:
  722.         for arg in args:
  723.             if isinstance(arg, TupleArg):
  724.                 numNames = len(misc.flatten(arg.names))
  725.                 argcount = argcount - numNames
  726.                 continue
  727.         
  728.     
  729.     return argcount
  730.  
  731.  
  732. def twobyte(val):
  733.     '''Convert an int argument into high and low bytes'''
  734.     if not isinstance(val, int):
  735.         raise AssertionError
  736.     return divmod(val, 256)
  737.  
  738.  
  739. class LineAddrTable:
  740.     """lnotab
  741.  
  742.     This class builds the lnotab, which is documented in compile.c.
  743.     Here's a brief recap:
  744.  
  745.     For each SET_LINENO instruction after the first one, two bytes are
  746.     added to lnotab.  (In some cases, multiple two-byte entries are
  747.     added.)  The first byte is the distance in bytes between the
  748.     instruction for the last SET_LINENO and the current SET_LINENO.
  749.     The second byte is offset in line numbers.  If either offset is
  750.     greater than 255, multiple two-byte entries are added -- see
  751.     compile.c for the delicate details.
  752.     """
  753.     
  754.     def __init__(self):
  755.         self.code = []
  756.         self.codeOffset = 0
  757.         self.firstline = 0
  758.         self.lastline = 0
  759.         self.lastoff = 0
  760.         self.lnotab = []
  761.  
  762.     
  763.     def addCode(self, *args):
  764.         for arg in args:
  765.             self.code.append(chr(arg))
  766.         
  767.         self.codeOffset = self.codeOffset + len(args)
  768.  
  769.     
  770.     def nextLine(self, lineno):
  771.         if self.firstline == 0:
  772.             self.firstline = lineno
  773.             self.lastline = lineno
  774.         else:
  775.             addr = self.codeOffset - self.lastoff
  776.             line = lineno - self.lastline
  777.             if line >= 0:
  778.                 push = self.lnotab.append
  779.                 while addr > 255:
  780.                     push(255)
  781.                     push(0)
  782.                     addr -= 255
  783.                 while line > 255:
  784.                     push(addr)
  785.                     push(255)
  786.                     line -= 255
  787.                     addr = 0
  788.                 if addr > 0 or line > 0:
  789.                     push(addr)
  790.                     push(line)
  791.                 
  792.                 self.lastline = lineno
  793.                 self.lastoff = self.codeOffset
  794.             
  795.  
  796.     
  797.     def getCode(self):
  798.         return ''.join(self.code)
  799.  
  800.     
  801.     def getTable(self):
  802.         return ''.join(map(chr, self.lnotab))
  803.  
  804.  
  805.  
  806. class StackDepthTracker:
  807.     
  808.     def findDepth(self, insts, debug = 0):
  809.         depth = 0
  810.         maxDepth = 0
  811.         for i in insts:
  812.             opname = i[0]
  813.             if debug:
  814.                 print i,
  815.             
  816.             delta = self.effect.get(opname, None)
  817.             if delta is not None:
  818.                 depth = depth + delta
  819.             else:
  820.                 for pat, pat_delta in self.patterns:
  821.                     if opname[:len(pat)] == pat:
  822.                         delta = pat_delta
  823.                         depth = depth + delta
  824.                         break
  825.                         continue
  826.                 
  827.                 if delta is None:
  828.                     meth = getattr(self, opname, None)
  829.                     if meth is not None:
  830.                         depth = depth + meth(i[1])
  831.                     
  832.                 
  833.             if depth > maxDepth:
  834.                 maxDepth = depth
  835.             
  836.             if debug:
  837.                 print depth, maxDepth
  838.                 continue
  839.         
  840.         return maxDepth
  841.  
  842.     effect = {
  843.         'POP_TOP': -1,
  844.         'DUP_TOP': 1,
  845.         'LIST_APPEND': -2,
  846.         'SLICE+1': -1,
  847.         'SLICE+2': -1,
  848.         'SLICE+3': -2,
  849.         'STORE_SLICE+0': -1,
  850.         'STORE_SLICE+1': -2,
  851.         'STORE_SLICE+2': -2,
  852.         'STORE_SLICE+3': -3,
  853.         'DELETE_SLICE+0': -1,
  854.         'DELETE_SLICE+1': -2,
  855.         'DELETE_SLICE+2': -2,
  856.         'DELETE_SLICE+3': -3,
  857.         'STORE_SUBSCR': -3,
  858.         'DELETE_SUBSCR': -2,
  859.         'PRINT_ITEM': -1,
  860.         'RETURN_VALUE': -1,
  861.         'YIELD_VALUE': -1,
  862.         'EXEC_STMT': -3,
  863.         'BUILD_CLASS': -2,
  864.         'STORE_NAME': -1,
  865.         'STORE_ATTR': -2,
  866.         'DELETE_ATTR': -1,
  867.         'STORE_GLOBAL': -1,
  868.         'BUILD_MAP': 1,
  869.         'COMPARE_OP': -1,
  870.         'STORE_FAST': -1,
  871.         'IMPORT_STAR': -1,
  872.         'IMPORT_NAME': -1,
  873.         'IMPORT_FROM': 1,
  874.         'LOAD_ATTR': 0,
  875.         'SETUP_EXCEPT': 3,
  876.         'SETUP_FINALLY': 3,
  877.         'FOR_ITER': 1,
  878.         'WITH_CLEANUP': -1 }
  879.     patterns = [
  880.         ('BINARY_', -1),
  881.         ('LOAD_', 1)]
  882.     
  883.     def UNPACK_SEQUENCE(self, count):
  884.         return count - 1
  885.  
  886.     
  887.     def BUILD_TUPLE(self, count):
  888.         return -count + 1
  889.  
  890.     
  891.     def BUILD_LIST(self, count):
  892.         return -count + 1
  893.  
  894.     
  895.     def CALL_FUNCTION(self, argc):
  896.         (hi, lo) = divmod(argc, 256)
  897.         return -(lo + hi * 2)
  898.  
  899.     
  900.     def CALL_FUNCTION_VAR(self, argc):
  901.         return self.CALL_FUNCTION(argc) - 1
  902.  
  903.     
  904.     def CALL_FUNCTION_KW(self, argc):
  905.         return self.CALL_FUNCTION(argc) - 1
  906.  
  907.     
  908.     def CALL_FUNCTION_VAR_KW(self, argc):
  909.         return self.CALL_FUNCTION(argc) - 2
  910.  
  911.     
  912.     def MAKE_FUNCTION(self, argc):
  913.         return -argc
  914.  
  915.     
  916.     def MAKE_CLOSURE(self, argc):
  917.         return -argc
  918.  
  919.     
  920.     def BUILD_SLICE(self, argc):
  921.         if argc == 2:
  922.             return -1
  923.         if argc == 3:
  924.             return -2
  925.  
  926.     
  927.     def DUP_TOPX(self, argc):
  928.         return argc
  929.  
  930.  
  931. findDepth = StackDepthTracker().findDepth
  932.